using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.IO;
using Microsoft.TeamFoundation.VersionControl.Client;
using Microsoft.TeamFoundation.Client;
using Ltf.Remoting.Settings;
using System.Runtime.InteropServices;
using System.Collections;
using Ltf.Remoting.RemoteEvents;
using Ltf.Remoting.TeamFoundation;
using ExtendedControls;
using Ltf.Remoting;
using System.Xml.Serialization;
using Ltf.Remoting.Operations;
using Lizard.Remoting.TFAccess;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using Ltf.Remoting.Server;
using Ltf.Remoting.TFAccess;
using Ltf.MonitorLizard.Helpers;
using Ltf.Remoting.Commands;
using System.Xml;
using Ltf.Diffs;

namespace Ltf.MonitorLizard.Forms
{
	[FormType(FormTypes.LizardReview)]

	public partial class LizardReview : Form
	{
		public enum SelectionType
		{
			Checked,
			Highlighted
		}

		private int sortColumnIndex = 0;
		private bool sortDesc = false;
		private Dictionary<string, ExtendedVirtualViewItem> listItemsByNames;

		private ExtendedListView.ExtendedVirtualViewItemCollection virtualItemCollection;

		// GroupIdx constants:
		private const int groupIdxConflict = 0;
		private const int groupIdxOutOfDate = 1;
		private const int groupIdxCheckedOutModified = 2;
		private const int groupIdxCheckedOutSame = 3;
		private const int groupIdxUncontrolledChange = 4;
		// Groups arrays index by groupIdx... constants
		private int[] GroupCounters = new int[] { 0, 0, 0, 0, 0, 0 };
		private bool[] GroupVisibility = new bool[] { true, true, true, true, true, false };

		private string[] pathList;

		private bool regenStatusFiles;
		private LizardTFItems cachedItems;

		private ReviewPrimaryFunction function;

		private event EventHandler ProgressIncrement;

		private Workspace workspace;

		private TFServerConnection connection;

		HistorySelector historySelector;




		public LizardReview(string[] pathList, LizardEventArgs args)
		{
			this.pathList = pathList;
			connection = ServerConnections.GetConnectionForPath(pathList[0]);
			workspace = connection.GetWorkspace(pathList[0]);
			InitializeComponent();

			listItemsByNames = new Dictionary<string, ExtendedVirtualViewItem>();
			virtualItemCollection = new ExtendedListView.ExtendedVirtualViewItemCollection(elvConflicts);
			Refresh();

			regenStatusFiles = true;
			cachedItems = null;
			elvConflicts.ColumnClick += new ColumnClickEventHandler(elvConflicts_ColumnClick);
			if (args is LizardReviewEventArgs)
			{
				LizardReviewEventArgs lrArgs = (LizardReviewEventArgs)args;

				tsbShowChanges.Checked = lrArgs.ShowPendings;
				tsbShowConflicts.Checked = lrArgs.ShowConflicts;
				tsbShowOutOfDate.Checked = lrArgs.ShowOutOfDate;
				tsbShowUnchangedPends.Checked = lrArgs.ShowUnchangedPendings;
				tsbShowUncontrolledChanges.Checked = false;

				tsbGetOptions.Checked = lrArgs.GetOptions;
				tsbCheckInComments.Checked = lrArgs.CheckinComments || lrArgs.ShelveOptions;
				tsbShelveOptions.Enabled = lrArgs.CheckinComments || lrArgs.ShelveOptions;
				tsbShelveOptions.Checked = lrArgs.ShelveOptions;
				function = lrArgs.Function;
				GroupVisibility = new bool[] { lrArgs.ShowConflicts, lrArgs.ShowOutOfDate, lrArgs.ShowPendings, lrArgs.ShowUnchangedPendings, false };
			}
			SetVisibilityAndPositions();
			if (pathList.Length == 1)
			{
				cmbGetVersion.Enabled = true;
				historySelector = new HistorySelector(cmbGetVersion, connection, workspace);
				LizardFileAccess.LoadVersions(connection, cmbGetVersion, pathList[0]);
				historySelector.Path = pathList[0];
			}
			else
			{
				cmbGetVersion.Text = "n/a";
				cmbGetVersion.Enabled = false;
			}

			LoadTree();
		}

		void elvConflicts_ColumnClick(object sender, ColumnClickEventArgs e)
		{
			elvConflicts.Invalidate(new Rectangle(0, 0, elvConflicts.Width, 20), false);
			elvConflicts.Refresh();
			elvConflicts.Columns[sortColumnIndex].ImageKey = null;
			if (sortColumnIndex == e.Column)
				sortDesc = !sortDesc;
			else
			{
				sortDesc = false;
				sortColumnIndex = e.Column;
			}
			if (sortDesc)
				elvConflicts.Columns[sortColumnIndex].ImageKey = "$down";
			else
				elvConflicts.Columns[sortColumnIndex].ImageKey = "$up";
			VirtualSorter sorter = new VirtualSorter((elvConflicts.ViewMode == ExtendedListViewMode.Tree), sortColumnIndex, sortDesc);
			virtualItemCollection.Sort(sorter);
			foreach (ExtendedVirtualViewItem evvi in virtualItemCollection)
			{
				evvi.Children.Sort(sorter);
			}
			elvConflicts.RedrawItems(0, virtualItemCollection.Count - 1, false);
		}

		private bool RaiseIncrement(string text)
		{
			ProgressIndicatorEventArgs piea = new ProgressIndicatorEventArgs(text);
			if (ProgressIncrement != null)
			{
				ProgressIncrement(this, piea);
				return piea.Cancel;
			}
			else
				return false;
		}

		private bool RaiseIncreasesIncrements(string text, int extraIncrements)
		{
			ProgressIndicatorEventArgs piea = new ProgressIndicatorEventArgs(text);
			piea.ReScale = true;
			piea.ExtraIncrements = extraIncrements;
			if (ProgressIncrement != null)
			{
				ProgressIncrement(this, piea);
				return piea.Cancel;
			}
			else
				return false;
		}
		private void btnCancel_Click(object sender, EventArgs e)
		{
			this.Close();
		}



		private void LoadGetPreviewList(LizardTFItems tfItems)
		{
			RaiseIncrement("Get workspace...");
			int version = 0;
			int.TryParse(cmbGetVersion.Text, out version);
			IEnumerable<TFInfoSet> items = tfItems.OutOfDateItemsets;
			if (version != 0)
				items = tfItems.GetDifferentVersionItemsets(version);

			foreach (TFInfoSet itemset in items)
			{
				if (itemset.Conflict != null && tsbShowConflicts.Checked)
				{
					bool isChecked = itemset.Conflict.CanMergeContent;
					ReviewRowColumns reviewRowColumns = new ReviewRowColumns(itemset);
					CreateReviewListItem(tfItems, reviewRowColumns, groupIdxConflict, isChecked, true);
				}
				else if (tsbShowOutOfDate.Checked)
				{
					bool isChecked = (function == ReviewPrimaryFunction.GetLatest || function == ReviewPrimaryFunction.GetSpecific);
					ReviewRowColumns reviewRowColumns = new ReviewRowColumns(itemset);
					CreateReviewListItem(tfItems, reviewRowColumns, groupIdxOutOfDate, isChecked, true);
				}
			}
		}


		private void LoadPendingList(LizardTFItems tfItems)
		{
			RaiseIncrement("Get pending changes...");
			if (!tsbShowChanges.Checked && !tsbShowUnchangedPends.Checked)
				return;
			List<TFInfoSet> changeList = new List<TFInfoSet>(tfItems.PendingItemsets);
			changeList.Sort(new Comparison<TFInfoSet>(CompareItemset));

			if (regenStatusFiles)
				RaiseIncreasesIncrements("Process pending changes...", changeList.Count);
			foreach (TFInfoSet itemset in changeList)
			{
				// if the item has been renamed we'll use the target name in the list
				string serverItem = itemset.ExtendedItem.SourceServerItem;
				string oldName = string.Empty;
				if ((itemset.PendingChange.ChangeType & ChangeType.Rename) == ChangeType.Rename)
				{
					serverItem = itemset.ExtendedItem.TargetServerItem;
					oldName = itemset.ExtendedItem.SourceServerItem;
					if (Path.GetDirectoryName(oldName) == Path.GetDirectoryName(serverItem))
						oldName = Path.GetFileName(oldName);
				}

				if (regenStatusFiles)
					RaiseIncrement("... getting status : " + Path.GetFileName(itemset.ExtendedItem.LocalItem));

				string testFile = itemset.ExtendedItem.LocalItem;
				string testStateImage = GetStateIcon(itemset.ExtendedItem, ref testFile);
				int group = (testStateImage == "CheckedOut" || testStateImage == "ServerConflict" || testStateImage == "Locked") ? groupIdxCheckedOutSame : groupIdxCheckedOutModified;
				if ((group == groupIdxCheckedOutSame && tsbShowUnchangedPends.Checked) || (group == groupIdxCheckedOutModified && tsbShowChanges.Checked))
				{
					ReviewRowColumns reviewRowColumns = new ReviewRowColumns(itemset);
					bool isChecked = (function == ReviewPrimaryFunction.Undo || function == ReviewPrimaryFunction.CheckIn || function == ReviewPrimaryFunction.Shelve);
					CreateReviewListItem(tfItems, reviewRowColumns, group, isChecked, true);
				}
			}
		}

		private void CreateReviewListItem(LizardTFItems tfItems, ReviewRowColumns columnData, int group, bool isChecked, bool folderCheckBoxes)
		{
			string file = columnData.LocalItem;
			if (string.IsNullOrEmpty(columnData.StateImage) && columnData.InfoSet != null)
				columnData.StateImage = GetStateIcon(columnData.InfoSet.ExtendedItem, ref file);

			ExtendedVirtualViewItem lvi;
			string dictName = string.Format("{0}|{1}", group, columnData.ItemPath);
			if (listItemsByNames.ContainsKey(dictName))
				lvi = listItemsByNames[dictName];
			else
			{
				lvi = new ExtendedVirtualViewItem(elvConflicts);
				listItemsByNames.Add(dictName, lvi);
			}

			string name = Path.GetFileName(columnData.ItemPath);
			ExtendedVirtualViewItem parent = GetParentExListItem(tfItems.RootPath, columnData.ItemPath, group, folderCheckBoxes);

			if (parent == null)
			{
				virtualItemCollection.Add(lvi);
				lvi.Group = elvConflicts.Groups[group];
			}
			else
				if (!parent.Children.Contains(lvi))
					parent.Children.Add(lvi);

			lvi.HasCheckbox = columnData.HasCheckbox;
			lvi.Checked = isChecked;
			if (columnData.IsRenamed)
				lvi.Text = string.Format("{0} ({1})", columnData.MainText, columnData.OldName);
			else
				lvi.Text = columnData.MainText;

			lvi.ImageKey = (columnData.ImageKey == null) ? file : columnData.ImageKey;
			lvi.Location = columnData.Location;
			if (columnData.StateImage != string.Empty)
				lvi.SecondaryImageKey = columnData.StateImage;

			List<string> subItems = new List<string>();
			subItems.Add(lvi.Text);
			subItems.Add(columnData.Version.ToString());
			subItems.Add(columnData.LatestVersion.ToString());
			subItems.Add(columnData.ChangeTypeText);
			subItems.Add(columnData.ConflictBaseChangeType);
			subItems.Add(columnData.ConflictBriefMessage);
			subItems.Add(Path.GetDirectoryName(columnData.LocalItem));
			lvi.Items = subItems.ToArray();

			lvi.IsExpanded = true;
			if (columnData.InfoSet != null)
				lvi.Tag = columnData.InfoSet;
			else
				lvi.Tag = columnData.StateImage + columnData.LocalItem;

			GroupCounters[group]++;

		}

		private void LoadUncontrolledList(LizardTFItems tfItems)
		{
			RaiseIncrement("Get uncontrolled changes...");
			if (!tsbShowUncontrolledChanges.Checked)
				return;

			string path1 = pathList[0];
			string path2 = workspace.GetServerItemForLocalItem(path1);
			IDifRepository tfsRepo = new LocalTFDifRepository(workspace.VersionControlServer, ServerConnections.DefaultConnection.Settings.TempPath);
			IDifRepository fsFiles = new FSDifRepository();

			List<string> ignoreList = new List<string>();
			foreach (TFInfoSet infoSet in tfItems.PendingItemsets)
			{
				string p = infoSet.ExtendedItem.LocalItem;
				if (p != null)
					ignoreList.Add(p);
			}


			DirDiffer dirDiffer = new DirDiffer(fsFiles, tfsRepo, path1, path1, string.Empty, ignoreList);
			tfsRepo.PrepCache(path1);
			dirDiffer.GoDiffs(tsbShowUncontrolledChanges.Checked);

			XmlDocument results = dirDiffer.Results;

			if (results == null)
				return;


			if (regenStatusFiles)
				RaiseIncreasesIncrements("Process uncontrolled changes...", results.SelectNodes("//*").Count);
			int i = 0;

			foreach (XmlNode node in results.SelectNodes("//*"))
			{
				if (node.Name.StartsWith("File") && node.Name != "FileSame" && node.Name != "FileMatches")
				{
					string fullname = node.Attributes["FileFullName"].Value;
					if (fullname.StartsWith("\\"))
						fullname = fullname.Substring(1);
					string path = Path.Combine(path1, fullname);
					if (!ignoreList.Contains(path))
					{

						string name = node.Attributes["FileName"].Value;
						ReviewRowColumns rowCols = new ReviewRowColumns()
						{
							MainText = name,
							ItemType = ItemType.File,
							IsRenamed = false,
							InfoSet = null,
							ItemPath = path,
							Version = 0,
							LatestVersion = 0,
							ChangeTypeText = "Uncontrolled",
							LocalItem = path,
							Location = path,
							ConflictBaseChangeType = string.Empty,
							ConflictBriefMessage = string.Empty
						};
						string file = path;
						GetStateIcon(null, ref file);
						switch (node.Name)
						{
							case "FileMissing":
								rowCols.ChangeTypeText = "New";
								rowCols.StateImage = "uncAdd";
								break;
							case "FileAdded":
								rowCols.ChangeTypeText = "Removed";
								rowCols.StateImage = "uncDel";
								break;
							default:
								rowCols.StateImage = "uncMod";
								break;
						}

						CreateReviewListItem(tfItems, rowCols, groupIdxUncontrolledChange, false, false);
					}
				}

			}
		}


		private int CompareItemset(TFInfoSet x, TFInfoSet y)
		{
			if (x.ExtendedItem.ItemType == ItemType.Folder)
				return x.ExtendedItem.SourceServerItem.CompareTo(y.ExtendedItem.SourceServerItem);
			else
				return Path.GetDirectoryName(x.ExtendedItem.SourceServerItem).CompareTo(Path.GetDirectoryName(y.ExtendedItem.SourceServerItem));
		}


		private string GetStateIcon(ExtendedItem extItem, ref string file)
		{
			Icon icon = null;
			string stateImageKey = string.Empty;
			if (file != null)
			{
				icon = Ltf.MonitorLizard.Helpers.FileIcons.GetFileIcon(file);
				if (extItem != null)
					stateImageKey = GetSecondaryImageKey(extItem, file);
			}
			else
			{
				string tmpFolder = connection.Settings.TempPath;
				string tmpFile = Path.Combine(tmpFolder, Path.GetFileName(extItem.SourceServerItem));
				if (!File.Exists(tmpFile))
					File.WriteAllText(tmpFile, string.Empty);
				icon = Ltf.MonitorLizard.Helpers.FileIcons.GetFileIcon(tmpFile);
				file = extItem.SourceServerItem;
				if ((extItem.ChangeType & ChangeType.Delete)!=0)
					stateImageKey = "Deleted";
				else
					stateImageKey = "Add";
				try
				{
					File.Delete(tmpFile);
				}
				catch { }
			}
			imlHeader.Images.Add(file, icon);
			return stateImageKey.ToLower();
		}



		#region new section for virtual items
		private ExtendedVirtualViewItem GetParentExListItem(Item rootItem, string name, int groupIndex)
		{
			if (elvConflicts.ViewMode == ExtendedListViewMode.List)
				return null;

			string pname = Path.GetDirectoryName(name);
			pname = pname.Replace('\\', '/');
			if (pname != null && pname != string.Empty && name != rootItem.ServerItem)
			{
				ExtendedVirtualViewItem parentElvi = GetParentExListItem(rootItem, pname, groupIndex);
				string dictName = string.Format("{0}|{1}", groupIndex, pname);
				if (!listItemsByNames.ContainsKey(dictName))
				{
					ExtendedVirtualViewItem elvi = new ExtendedVirtualViewItem(elvConflicts);
					elvi.Text = pname;
					listItemsByNames.Add(dictName, elvi);
					elvi.ImageKey = "$folder";
					elvi.ForeColor = SystemColors.GrayText;
					elvi.HasCheckbox = false;
					elvi.Location = Path.GetDirectoryName(name);
					if (parentElvi != null)
						parentElvi.Children.Add(elvi);
					else
					{
						elvi.Group = elvConflicts.Groups[groupIndex];
						virtualItemCollection.Add(elvi);
					}
					elvi.IsExpanded = true;
					elvi.IsFolder = true;
					return elvi;
				}
				else
				{
					return listItemsByNames[dictName];
				}
			}
			return null;
		}

		private ExtendedVirtualViewItem GetParentExListItem(string rootItemPath, string name, int groupIndex, bool hasCheckbox)
		{
			if (elvConflicts.ViewMode == ExtendedListViewMode.List)
				return null;

			string pname = Path.GetDirectoryName(name);
			if (pname == null && name != string.Empty)
				pname = name.Substring(0, 1);
			if (pname != null)
				pname = pname.Replace('\\', '/');
			if (pname != null && pname != string.Empty && name != rootItemPath && name != pathList[0].Replace('\\', '/'))
			{
				ExtendedVirtualViewItem parentElvi = GetParentExListItem(rootItemPath, pname, groupIndex, hasCheckbox);
				string dictName = string.Format("{0}|{1}", groupIndex, pname);
				if (!listItemsByNames.ContainsKey(dictName))
				{
					ExtendedVirtualViewItem elvi = new ExtendedVirtualViewItem(elvConflicts);
					elvi.Text = pname;
					listItemsByNames.Add(dictName, elvi);
					elvi.ImageKey = "$folder";
					elvi.ForeColor = SystemColors.GrayText;
					elvi.HasCheckbox = hasCheckbox;
					elvi.Location = Path.GetDirectoryName(name);
					elvi.IsFolder = true;
					if (parentElvi != null)
						parentElvi.Children.Add(elvi);
					else
					{
						elvi.Group = elvConflicts.Groups[groupIndex];
						virtualItemCollection.Add(elvi);
					}
					elvi.IsExpanded = true;
					return elvi;
				}
				else
				{
					return listItemsByNames[dictName];
				}
			}
			return null;
		}

		#endregion

		private int ShowChildren(ExtendedVirtualViewItem item, int itemIdx)
		{
			int insertIdx = 0;
			if (item.Children.Count > 0)
			{
				item.Children.Sort(new VirtualSorter((elvConflicts.ViewMode == ExtendedListViewMode.Tree), sortColumnIndex, sortDesc));
				foreach (ExtendedVirtualViewItem childItem in item.Children)
				{
					childItem.IsRedrawRequired = true;
					if (item.Group != null)
						childItem.Group = item.Group;
					//			if (!base.Items.Contains(item))
					try
					{
						virtualItemCollection.Insert(itemIdx + ++insertIdx, childItem);
						childItem.Depth = item.Depth + 1;
						childItem.ParentItem = item;
					}
					catch (Exception ex)
					{
						// It must already be somewhere else!
					}
					if (childItem.IsExpanded || elvConflicts.ViewMode == ExtendedListViewMode.List)
					{

						insertIdx += ShowChildren(childItem, virtualItemCollection.IndexOf(childItem));
					}
				}
			}
			item.IsExpanded = true;
			elvConflicts.VirtualListSize = virtualItemCollection.Count;
			return insertIdx;

		}

		public void HideChildren(ExtendedVirtualViewItem item, int itemIdx)
		{
			if (!item.IsExpanded)
				return;
			if (item.Children.Count > 0)
			{
				int hideIdx = itemIdx + 1;
				foreach (ExtendedVirtualViewItem childItem in item.Children)
				{
					childItem.IsRedrawRequired = true;
					if (childItem.IsExpanded)
					{
						HideChildren(childItem, virtualItemCollection.IndexOf(childItem));
						childItem.IsExpanded = true;
					}


					virtualItemCollection.RemoveAt(hideIdx);
				}
			}
			item.IsExpanded = false;
			elvConflicts.VirtualListSize = virtualItemCollection.Count;
		}


		private void elvConflicts_SelectedIndexChanged(object sender, EventArgs e)
		{

		}

		private string GetSecondaryImageKey(ExtendedItem extItem, string fileName)
		{
			string folderName = Path.GetDirectoryName(fileName);
			LizardOverLayStatus olt = LizardOverLayStatus.Add;

			string ltfvcFolder = connection.GetMetaFolder(Path.GetDirectoryName(fileName));
			string ltfvcFile = ltfvcFolder + "\\" + Path.GetFileName(fileName) + ".ltfvc";
			string ltfvcServerFile = ltfvcFolder + "\\" + Path.GetFileName(fileName) + ".server";


			if (Directory.Exists(ltfvcFolder))
			{
				if (File.Exists(fileName))
				{
					//regen, just in case...
					if (regenStatusFiles)
					{
						Ltf.Remoting.Commands.GenerateOverlayInfo goi = new Ltf.Remoting.Commands.GenerateOverlayInfo(connection);
						goi.GenerateFileStatus(extItem, false, workspace);
					}
					string content = File.ReadAllText(ltfvcFile);
					LizardFileInfo fi = GetFileInfoFromFile(ltfvcFile);
					olt = fi.OverlayType;
					//}
				}
				else if (Directory.Exists(fileName))
				{
					string metaPath = ServerConnections.GetConnectionForPath(fileName).GetMetaFolder(fileName);
					string statusFile = Path.Combine(fileName, "ltfvc.folderstatus");
					if (File.Exists(statusFile))
					{
						string status = File.ReadAllText(statusFile);
						olt = (LizardOverLayStatus)Enum.Parse(typeof(LizardOverLayStatus), status);
					}
				}
			}
			return olt.ToString();
		}
		private LizardFileInfo GetFileInfoFromFile(string fileName)
		{
			LizardFileInfo fileInfo = null;
			XmlSerializer xs = new XmlSerializer(typeof(LizardFileInfo));
			using (Stream s = new FileStream(fileName, FileMode.Open))
			{
				fileInfo = (LizardFileInfo)xs.Deserialize(s);
			}
			return fileInfo;
		}

		private void tsbTreeView_Click(object sender, EventArgs e)
		{
			regenStatusFiles = false;
			BuildTree();

		}

		private void LoadTree()
		{
			using (Busy busy = new Busy("Processing...", "Checking item status...", 10, 1, false))
			{
				if (cachedItems == null)
				{
					int version = 0;
					int.TryParse(cmbGetVersion.Text, out version);

					WorkspaceOperators wso = new WorkspaceOperators(connection, connection.GetWorkspace(pathList[0]));
					LizardTFItems tfItems = wso.GetTFItems(pathList, version);
					cachedItems = tfItems;
				}

				ProgressIncrement += busy.IncrementHandler;
				BuildTree();
				ProgressIncrement -= busy.IncrementHandler;
			}
		}

		private void BuildTree()
		{
			virtualItemCollection = new ExtendedListView.ExtendedVirtualViewItemCollection(elvConflicts);

			listItemsByNames.Clear();
			GroupCounters = new int[] { 0, 0, 0, 0, 0 };
			elvConflicts.BeginUpdate();
			elvConflicts.ViewMode = ExtendedListViewMode.Tree;
			LoadGetPreviewList(cachedItems);

			LoadPendingList(cachedItems);

			LoadUncontrolledList(cachedItems);


			List<ExtendedVirtualViewItem> rootListItems = new List<ExtendedVirtualViewItem>(virtualItemCollection);
			foreach (ExtendedVirtualViewItem elvi in rootListItems)
			{
				ShowChildren(elvi, virtualItemCollection.IndexOf(elvi));
			}

			AddGroupHeaders();

			elvConflicts.VirtualListSize = virtualItemCollection.Count;

			virtualItemCollection.Sort(new VirtualSorter((elvConflicts.ViewMode == ExtendedListViewMode.Tree), sortColumnIndex, sortDesc));

			elvConflicts.EndUpdate();
		}

		private void tsbListView_Click(object sender, EventArgs e)
		{
			regenStatusFiles = false;
			BuildList();
		}

		private void LoadList()
		{
			using (Busy busy = new Busy("Processing...", "Checking item status...", 10, 1, false))
			{
				if (cachedItems == null)
				{
					WorkspaceOperators wso = new WorkspaceOperators(connection, connection.GetWorkspace(pathList[0]));
					LizardTFItems tfItems = wso.GetTFItems(pathList);
					cachedItems = tfItems;
				}

				ProgressIncrement += busy.IncrementHandler;

				BuildList();

				ProgressIncrement -= busy.IncrementHandler;

			}
		}

		private void BuildList()
		{
			listItemsByNames.Clear();
			GroupCounters = new int[] { 0, 0, 0, 0, 0 };
			elvConflicts.ViewMode = ExtendedListViewMode.List;
			elvConflicts.BeginUpdate();
			virtualItemCollection = new ExtendedListView.ExtendedVirtualViewItemCollection(elvConflicts);
			LoadGetPreviewList(cachedItems);

			LoadPendingList(cachedItems);

			AddGroupHeaders();


			elvConflicts.VirtualListSize = virtualItemCollection.Count;

			virtualItemCollection.Sort(new VirtualSorter((elvConflicts.ViewMode == ExtendedListViewMode.Tree), sortColumnIndex, sortDesc));


			elvConflicts.Invalidate();
			elvConflicts.EndUpdate();
		}

		private void AddGroupHeaders()
		{

			foreach (ListViewGroup g in elvConflicts.Groups)
				AddGroupHeader(g);
		}

		private ExtendedVirtualViewItem AddGroupHeader(ListViewGroup g)
		{
			int grpIdx = elvConflicts.Groups.IndexOf(g);
			if (GroupVisibility[grpIdx])
			{
				ExtendedVirtualViewItem groupheader = new ExtendedVirtualViewItem(elvConflicts);
				groupheader.Items = new string[] { string.Format("{0} - {1} item(s)", g.Header, GroupCounters[grpIdx]) };
				groupheader.ForeColor = Color.DarkSlateBlue;
				groupheader.GroupHeaderIdx = -2;
				groupheader.Group = g;
				virtualItemCollection.Add(groupheader);

				groupheader = new ExtendedVirtualViewItem(elvConflicts);
				groupheader.Items = new string[] { "-" };
				groupheader.GroupHeaderIdx = -1;
				groupheader.Group = g;
				virtualItemCollection.Add(groupheader);
				return groupheader;
			}
			else
				return null;
		}

		private void RefreshView()
		{
			regenStatusFiles = true;
			cachedItems = null;
			if (elvConflicts.ViewMode == ExtendedListViewMode.List)
				LoadList();
			else
				LoadTree();

		}
		private void btnGet_Click(object sender, EventArgs e)
		{
			GetLatestVersions();
		}

		private void GetLatestVersions()
		{
			List<string> files = new List<string>();
			foreach (int group in new int[] { 0, 1 })
			{
				foreach (ExtendedVirtualViewItem extVLvi in virtualItemCollection)
				{
					if (extVLvi.GroupIdx == group)
					{
						if (extVLvi.Checked && extVLvi.Tag is TFInfoSet)
							files.Add(((TFInfoSet)extVLvi.Tag).ExtendedItem.SourceServerItem);
					}
				}

			}

			VersionSpec versionSpec = VersionSpec.Latest;
			int version = 0;
			int.TryParse(cmbGetVersion.Text, out version);
			if (version != 0)
				versionSpec = new ChangesetVersionSpec(version);
			GetLatestVersions(files.ToArray(), versionSpec, chbOverWrite.Checked, chbForceGet.Checked);
		}

		private void GetLatestVersions(string[] files, VersionSpec versionSpec, bool overWrite, bool forceGet)
		{
			using (BusyIndicator bi = new BusyIndicator("LizardTF Get", "Getting...", false))
			{
				if (files.Length > 0)
				{
					string file = files[0];
					try
					{

						WorkspaceOperators wso = new WorkspaceOperators(connection, connection.GetWorkspace(pathList[0]), bi);
						GetStatus gs = wso.Get(files, versionSpec, RecursionType.None, overWrite, forceGet);
						wso.BusyMessageReceiver = null;
						string results = string.Format("Updates:{0}\r\nWarnings:{1}\r\nConflicts:{2}\r\n",
							gs.NumOperations - gs.NumConflicts - gs.NumWarnings, gs.NumWarnings, gs.NumConflicts);
						MessageBox.Show("Get Operation Complete:\r\n" + results, "Get Complete.");
						RefreshView();
					}

					catch (Exception ex)
					{
						MessageBox.Show("Get operation failed with the message :" + ex.Message, "Get Failed");
						return;
					}
				}
				else
				{
					MessageBox.Show("No items have been checked for update.", "No Selection");
				}
			}
		}

		private void CheckInVersions(SelectionType selectionType)
		{
			if (txtComments.Text == string.Empty)
			{
				MessageBox.Show("Please supply a comment for this check-in.", "No Check-In comments.");
				return;
			}
			List<PendingChange> changes = new List<PendingChange>();
			foreach (int group in new int[] { 2, 3 })
			{

				foreach (ExtendedVirtualViewItem extVLvi in virtualItemCollection)
				{
					bool selected = (selectionType == SelectionType.Checked && extVLvi.Checked)
						|| (selectionType == SelectionType.Highlighted && contextMenuKeys.Contains(extVLvi.key));

					if (extVLvi.GroupIdx == group && extVLvi.GroupHeaderIdx == 0)
					{
						if (selected && extVLvi.Tag != null && extVLvi.Tag is TFInfoSet)
						{
							TFInfoSet itemset = (TFInfoSet)extVLvi.Tag;
							PendingChange pc = itemset.PendingChange;
							if (pc != null)
								changes.Add(pc);
						}
					}
				}

			}
			CheckInVersions(changes);
		}

		private void CheckInVersions(List<PendingChange> changes)
		{

			if (changes.Count > 0)
			{
				using (new HourGlass(this))
				{
					int[] workItems = new int[] { };
					try
					{
						workItems = GetSelectedWorkItems();
					}
					catch (ArgumentException argEx)
					{
						MessageBox.Show(argEx.Message, "Invalid WorkItems");
						return;
					}
					try
					{
						WorkspaceOperators wso = new WorkspaceOperators(connection, connection.GetWorkspace(pathList[0]));
						int cs = wso.CheckIn(changes.ToArray(), txtComments.Text, workItems, chbResolveWorkItems.Checked);
						if (cs > 0)
							MessageBox.Show("Check-in operation completed and created changeset :" + cs.ToString(), "Check-In Complete");
						else
							MessageBox.Show("Check-in operation completed, no files changed and no changeset created.", "Check-In Complete");
					}
					catch (Exception ex)
					{
						MessageBox.Show("Check-in operation failed with the message :" + ex.Message, "Check-In Failed");
						return;
					}
					RefreshView();
				}
			}
			else
			{
				MessageBox.Show("No items have been checked for checking in.", "No Selection");
			}
		}

		private void ShelveChangeset(SelectionType selectionType)
		{
			if (txtComments.Text == string.Empty)
			{
				MessageBox.Show("Please supply a comment for this shelve operations.", "No Shelve Comments.");
				return;
			}
			List<PendingChange> changes = new List<PendingChange>();
			string name = string.Empty;
			foreach (int group in new int[] { 2, 3 })
			{
				foreach (ExtendedVirtualViewItem extVLvi in virtualItemCollection)
				{
					bool selected = (selectionType == SelectionType.Checked && extVLvi.Checked)
					|| (selectionType == SelectionType.Highlighted && contextMenuKeys.Contains(extVLvi.key));

					if (extVLvi.GroupIdx == group && extVLvi.GroupHeaderIdx == 0)
					{
						if (selected && extVLvi.Tag != null && extVLvi.Tag is TFInfoSet)
						{
							TFInfoSet itemset = (TFInfoSet)extVLvi.Tag;
							PendingChange pc = itemset.PendingChange;
							if (pc != null)
								changes.Add(pc);
						}
					}
				}

			}
			ShelveChangeset(changes);
		}

		private void ShelveChangeset(List<PendingChange> changes)
		{

			if (changes.Count > 0)
			{
				using (new HourGlass(this))
				{
					int[] workItems = new int[] { };
					try
					{
						workItems = GetSelectedWorkItems();
					}
					catch (ArgumentException argEx)
					{
						MessageBox.Show(argEx.Message, "Invalid WorkItems");
						return;
					}
					try
					{
						WorkspaceOperators wso = new WorkspaceOperators(connection, connection.GetWorkspace(pathList[0]));
						string user = wso.Shelve(changes.ToArray(), txtShelveName.Text, txtComments.Text, workItems,
							ckbReplaceExisting.Checked, ckbShelveRevert.Checked);
						MessageBox.Show("Shelve operation completed and created shelveset :" + user + "/" + txtShelveName.Text, "Shelve Complete");
					}
					catch (Exception ex)
					{
						MessageBox.Show("Shelve operation failed with the message :" + ex.Message, "Shelve Failed");
						return;
					}
					RefreshView();
				}
			}
			else
			{
				MessageBox.Show("No items have been checked for shelving.", "No Selection");
			}
		}

		private void UndoPendings(SelectionType selectionType)
		{
			List<PendingChange> changes = new List<PendingChange>();
			int changedCount = 0;
			foreach (int group in new int[] { 2, 3 })
			{
				foreach (ExtendedVirtualViewItem extVLvi in virtualItemCollection)
				{
					if (extVLvi.GroupIdx == group && extVLvi.GroupHeaderIdx == 0)
					{
						bool selected = (selectionType == SelectionType.Checked && extVLvi.Checked)
							 || (selectionType == SelectionType.Highlighted && contextMenuKeys.Contains(extVLvi.key));
						if (selected && extVLvi.Tag != null && extVLvi.Tag is TFInfoSet)
						{
							if (extVLvi.GroupIdx == 2)
								changedCount++;
							TFInfoSet itemset = (TFInfoSet)extVLvi.Tag;
							PendingChange pc = itemset.PendingChange;
							if (pc != null)
								changes.Add(pc);
						}
					}
				}

			}

			if (changedCount > 0)
			{
				DialogResult dr = MessageBox.Show("Do you want to Undo the check-outs and loose any changes you have made?", "Undo Checkouts?",
					MessageBoxButtons.OKCancel, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2);
				if (dr == DialogResult.Cancel)
					return;
			}


			if (changes.Count > 0)
			{


				using (new HourGlass(this))
				{
					try
					{
						WorkspaceOperators wso = new WorkspaceOperators(connection, connection.GetWorkspace(pathList[0]));
						wso.UndoPending(changes.ToArray());
						MessageBox.Show("Undo operation completed.", "Undo Complete");
						RefreshView();
					}
					catch (Exception ex)
					{
						MessageBox.Show("Undo operation failed with the message :" + ex.Message, "Undo Failed");
						return;
					}
				}
			}
			else
			{
				MessageBox.Show("No items have been checked for Undo.", "No Selection");
			}
		}


		private void tsbRefresh_Click(object sender, EventArgs e)
		{
			RefreshView();
		}

		private void tsbShowOption_Click(object sender, EventArgs e)
		{
			Refresh();
			GroupVisibility = new bool[] { tsbShowConflicts.Checked, tsbShowOutOfDate.Checked, tsbShowChanges.Checked, tsbShowUnchangedPends.Checked, tsbShowUncontrolledChanges.Checked };

			using (new HourGlass(this))
			{
				if (elvConflicts.ViewMode == ExtendedListViewMode.List)
					BuildList();
				else
					BuildTree();
			}
		}

		private void tsbSections_Click(object sender, EventArgs e)
		{
			SetVisibilityAndPositions();
		}

		private void chbOverWrite_CheckedChanged(object sender, EventArgs e)
		{

		}

		private void SetVisibilityAndPositions()
		{
			tsbShelveOptions.Enabled = tsbCheckInComments.Checked;
			grbComments.Height = tsbShelveOptions.Checked ? 145 : 103;
			pnlCheckinComments.Top = tsbShelveOptions.Checked ? pnlShelveOptions.Top + pnlShelveOptions.Height : pnlShelveOptions.Top;
			pnlShelveOptions.Visible = tsbShelveOptions.Checked;
			grbComments.Top = tsMainToolBar.Bottom + 3;
			grbGetOptions.Top = grbComments.Top + (tsbCheckInComments.Checked ? grbComments.Height : 0) + 3;
			elvConflicts.Top = grbGetOptions.Top + (tsbGetOptions.Checked ? grbGetOptions.Height : 0) + 3;

			elvConflicts.Height = this.Height - elvConflicts.Top - 67;

			grbComments.Visible = tsbCheckInComments.Checked;
			grbGetOptions.Visible = tsbGetOptions.Checked;
			btnCheckIn.Text = tsbShelveOptions.Checked ? "Shelve" : "Check &In";
			grbComments.Text = tsbShelveOptions.Checked ? "Shelveset Options" : "Check In Comments";
		}

		private void tsbGetVersion_Click(object sender, EventArgs e)
		{
			GetLatestVersions();
		}

		private void tsbCheckIn_Click(object sender, EventArgs e)
		{
			CheckInVersions(SelectionType.Checked);
		}

		private void tsbUndoPending_Click(object sender, EventArgs e)
		{
			UndoPendings(SelectionType.Checked);
		}

		private void btnCheckIn_Click(object sender, EventArgs e)
		{
			if (tsbShelveOptions.Enabled && tsbShelveOptions.Checked)
				ShelveChangeset(SelectionType.Checked);
			else
				CheckInVersions(SelectionType.Checked);
		}



		private void btnUndoPending_Click(object sender, EventArgs e)
		{
			UndoPendings(SelectionType.Checked);
		}

		private void btnCheckAll_Click(object sender, EventArgs e)
		{
			foreach (ExtendedVirtualViewItem elvvi in virtualItemCollection)
			{
				elvvi.Checked = true;
				elvvi.FolderCheckState = FolderCheckState.Checked;
			}
			elvConflicts.Refresh();
		}

		private void btnUncheckAll_Click(object sender, EventArgs e)
		{
			foreach (ExtendedVirtualViewItem elvvi in virtualItemCollection)
			{
				elvvi.Checked = false;
				elvvi.FolderCheckState = FolderCheckState.Unchecked;
			}
			elvConflicts.Refresh();
		}

		public int[] GetSelectedWorkItems()
		{
			if (txtWorkItems.Text.Trim() == string.Empty)
				return new int[] { };
			WorkItemStore workItemStore = new WorkItemStore(connection.TeamFoundationServer);
			string[] itemNumbers = txtWorkItems.Text.Split(',');
			List<int> validItemIds = new List<int>();
			List<string> invalidItemNumbers = new List<string>();
			foreach (string itemNumber in itemNumbers)
			{
				int itemId;
				if (int.TryParse(itemNumber, out itemId))
				{
					try
					{
						workItemStore.GetWorkItem(itemId);
						validItemIds.Add(itemId);
					}
					catch (Exception ex)
					{
						invalidItemNumbers.Add(itemNumber);
					}

				}
				else
				{
					invalidItemNumbers.Add(itemNumber);
				}
			}
			if (invalidItemNumbers.Count == 0)
				return validItemIds.ToArray();

			throw new ArgumentException(string.Format("The following are not valid workitem ids : {0}", string.Join(", ", invalidItemNumbers.ToArray())));

		}

		private MouseButtons lastButton = MouseButtons.None;
		private string contextMenuPathList = string.Empty;
		private List<int> contextMenuKeys = new List<int>();

		private void elvConflicts_MouseDown(object sender, MouseEventArgs e)
		{
			lastButton = e.Button;
		}
		/// <summary>
		/// Raises the <see cref="E:System.Windows.Forms.Control.Click"></see> event.
		/// </summary>
		/// <param name="e">An <see cref="T:System.EventArgs"></see> that contains the event data.</param>
		private void elvConflicts_Click(object sender, EventArgs e)
		{
			contextMenuKeys = new List<int>();
			Point hit = elvConflicts.PointToClient(MousePosition);
			ListViewHitTestInfo hti = elvConflicts.HitTest(hit);
			if (hti.Item is ExtendedListViewItem)
			{
				StringBuilder sb = new StringBuilder();
				StringBuilder uncSb = new StringBuilder();
				List<string> stringTags = new List<string>();
				ExtendedListViewItem elvi = hti.Item as ExtendedListViewItem;
				if (lastButton == MouseButtons.Right)
				{
					foreach (int idx in elvConflicts.SelectedIndices)
					{
						ExtendedVirtualViewItem lvi = virtualItemCollection[idx];
						if (lvi.Tag is TFInfoSet)
						{
							contextMenuKeys.Add(lvi.key);
							sb.Append(string.Format("\"{0}\" ", ((TFInfoSet)lvi.Tag).ExtendedItem.LocalItem));
						}
						else if (lvi.Tag is string && !stringTags.Contains(lvi.Tag.ToString()))
						{
							stringTags.Add(lvi.Tag.ToString().Substring(0, 6));
							uncSb.Append(string.Format("\"{0}\" ", lvi.Tag.ToString().Substring(6)));
						}
					}
					cmsFileNode.Items.Clear();
					if (sb.Length == 0)
					{
						string[] AddItems = new string[] { "Add to TFS", "Delete local" };
						string[] DelItems = new string[] { "Delete from TFS", "Replace local" };
						string[] ModItems = new string[] { "Checkout from TFS", "Revert local" };
						foreach (string s in AddItems)
						{
							ToolStripItem menuItem = cmsFileNode.Items.Add(s, null, contextMenu_Click);
							menuItem.Name = s;
							menuItem.Enabled = !stringTags.Contains("uncDel") && !stringTags.Contains("uncMod");
						}
						foreach (string s in ModItems)
						{
							ToolStripItem menuItem = cmsFileNode.Items.Add(s, null, contextMenu_Click);
							menuItem.Name = s;
							menuItem.Enabled = !stringTags.Contains("uncDel") && !stringTags.Contains("uncAdd");
						}
						foreach (string s in DelItems)
						{
							ToolStripItem menuItem = cmsFileNode.Items.Add(s, null, contextMenu_Click);
							menuItem.Name = s;
							menuItem.Enabled = !stringTags.Contains("uncAdd") && !stringTags.Contains("uncMod");
						}
						cmsFileNode.Show(elvConflicts, hit);
						contextMenuPathList = uncSb.ToString();
						return;
					}
					ServerFunctions sf = new ServerFunctions();
					Dictionary<string, ContextMenuAttribute> menus = sf.GetMenus(sb.ToString(), ContextMenuUsage.ReviewOnly);
					foreach (KeyValuePair<string, ContextMenuAttribute> kvp in menus)
					{
						ToolStripItem menuItem = cmsFileNode.Items.Add(kvp.Value.Text, null, contextMenu_Click);
						menuItem.Name = kvp.Value.Name;
						menuItem.Enabled = !kvp.Value.Disabled;

					}
					if (elvConflicts.SelectedIndices.Count == 1 && virtualItemCollection[elvConflicts.SelectedIndices[0]].Tag is TFInfoSet)
					{
						TFInfoSet infoSet = (TFInfoSet)virtualItemCollection[elvConflicts.SelectedIndices[0]].Tag;

						string serverItem = infoSet.ExtendedItem.SourceServerItem;
						if (infoSet.ExtendedItem != null)
						{
							ExtendedItem extItem = infoSet.ExtendedItem;
							if (!string.IsNullOrEmpty(extItem.LocalItem))
							{
								Workspace workspace = connection.GetWorkspace(extItem.LocalItem);
								ContextMenus.LoadDiffMenu(cmsFileNode, extItem.LocalItem,
									"Compare with ", connection, workspace);
							}
						}

					}
					contextMenuPathList = sb.ToString();
					cmsFileNode.Show(elvConflicts, hit);
				}
			}
		}

		private void contextMenu_Click(object sender, EventArgs e)
		{
			if (sender is ToolStripItem)
			{
				ToolStripItem menuItem = (ToolStripItem)sender;
				ServerFunctions sf = new ServerFunctions();
				switch (menuItem.Name)
				{
					case "history":
						sf.ShowHistory(contextMenuPathList);
						break;

					case "diff":
						sf.Diff(contextMenuPathList);
						break;
					case "blame":
						sf.Blame(contextMenuPathList);
						break;
					case "resolveconflict":
						sf.ResolveConflict(contextMenuPathList);
						break;
					case "properties":
						FilePropertiesLauncher.ShowProperties(contextMenuPathList.Replace("\"", ""), this.Handle);
						break;
					case "checkoutlock":
						string[] paths = ServerFunctions.GetPaths(contextMenuPathList);
						CheckOutLock col = new CheckOutLock(paths, new LizardEventArgs(paths, FormTypes.CheckOutLock));
						col.ShowDialog();
						RefreshView();
						break;
					case "undopending":
						UndoPendings(SelectionType.Highlighted);
						break;
					case "checkin":
						CheckInVersions(SelectionType.Highlighted);
						break;
					case "shelve":
						ShelveChangeset(SelectionType.Highlighted);
						break;
					case "unshelve":
						sf.Unshelve(contextMenuPathList);
						break;
					case "Add to TFS":
						sf.Add(contextMenuPathList);
						RefreshView();
						break;
					case "Delete local":
						DeleteSelectionFromFS();
						RefreshView();
						break;
					case "Delete from TFS":
						DeleteSelectionFromTFS();
						RefreshView();
						break;
					case "Replace local":
						ReplaceSelectionFromTFS(false);
						break;
					case "Checkout from TFS":
						sf.CheckOut(contextMenuPathList);
						RefreshView();
						break;
					case "Revert local":
						ReplaceSelectionFromTFS(true);
						break;
					case "":
						break;
					default:
						MessageBox.Show("This function has not been implemented from the context menu yet.", "Not Implemented");
						break;

				}
			}
		}

		private void DeleteSelectionFromFS()
		{
			ServerFunctions sf = new ServerFunctions();
			DialogResult dr = MessageBox.Show("Are you sure you want to permanently delete the selection from the file system?", "Delete Files", MessageBoxButtons.YesNo,
				MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2);
			if (dr == DialogResult.Yes)
			{
				string[] deletePaths = ServerFunctions.GetPaths(contextMenuPathList);
				bool abort = false;
				foreach (string deletePath in deletePaths)
				{
					DialogResult dr2 = DialogResult.Retry;
					while (dr2 == DialogResult.Retry)
					{
						try
						{
							File.Delete(deletePath);
							dr2 = DialogResult.OK;
						}
						catch (Exception ex)
						{
							string deleteErrorMsg = string.Format("The error:\r\n{0}\r\n\r\noccurred while trying to delete the file '{1}'. Do you wish to continue trying to delete files ?",
								ex.Message, deletePath);
							dr2 = MessageBox.Show(deleteErrorMsg, "Error During Delete File", MessageBoxButtons.AbortRetryIgnore,
								MessageBoxIcon.Warning, MessageBoxDefaultButton.Button3);
							if (dr2 == DialogResult.Abort)
								break;
						}
					}
					if (abort)
						break;
				}
			}

		}

		private void DeleteSelectionFromTFS()
		{
			ServerFunctions sf = new ServerFunctions();
			DialogResult dr = MessageBox.Show("Are you sure you want to permanently delete the selection from the TF repository?", "Delete Files", MessageBoxButtons.YesNo,
				MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2);
			if (dr == DialogResult.Yes)
			{
				try
				{
					sf.Delete(contextMenuPathList);
				}
				catch (Exception ex)
				{
					string deleteErrorMsg = string.Format("The error:\r\n{0}\r\n\r\noccurred while trying to delete the file(s).",
						ex.Message);
					MessageBox.Show(deleteErrorMsg, "Error During TFS Delete", MessageBoxButtons.OK,
						MessageBoxIcon.Warning);

				}
			}
		}

		private void ReplaceSelectionFromTFS(bool isCheckRequired)
		{
			ServerFunctions ServerFunctions = new ServerFunctions();
			DialogResult dr = DialogResult.Yes;
			if (isCheckRequired)
			{
				dr = MessageBox.Show("Are you sure you want to replace the selection with the latest version from the TF repository?", "Replace Files", MessageBoxButtons.YesNo,
				 MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2);
			}
			if (dr == DialogResult.Yes)
			{
				try
				{
					string[] paths = ServerFunctions.GetPaths(contextMenuPathList);
					VersionSpec vs = VersionSpec.Latest;
					GetLatestVersions(paths, vs, true, true);
				}
				catch (Exception ex)
				{
					string deleteErrorMsg = string.Format("The error:\r\n{0}\r\n\r\noccurred while trying to fetch the file(s).",
						ex.Message);
					MessageBox.Show(deleteErrorMsg, "Error During TFS Get", MessageBoxButtons.OK,
						MessageBoxIcon.Warning);

				}
			}
		}

		private void cmbGetVersion_SelectedIndexChanged(object sender, EventArgs e)
		{
			RefreshView();
		}

		private void cmDiffFileNode_Popup(object sender, EventArgs e)
		{

		}

		private void btnNewWorkItem_Click(object sender, EventArgs e)
		{
			while (cmsNewWorkitem.Items.Count > 0)
				cmsNewWorkitem.Items.RemoveAt(0);

			WorkItemStore wis = new WorkItemStore(connection.TeamFoundationServer);
			WorkItemTypeCollection witc = wis.Projects[workspace.GetTeamProjectForLocalPath(pathList[0]).Name].WorkItemTypes;
			foreach (WorkItemType wit in witc)
			{
				ToolStripItem tsi = cmsNewWorkitem.Items.Add(string.Format("New {0}", wit.Name));
				tsi.Click += new EventHandler(NewWorkItemMenu_Click);
				tsi.Tag = wit;
			}
			cmsNewWorkitem.Show(btnNewWorkItem, new Point(4, 4));
		}

		void NewWorkItemMenu_Click(object sender, EventArgs e)
		{
			if (sender is ToolStripItem)
			{
				ToolStripItem tsi = (ToolStripItem)sender;
				if (tsi.Tag is WorkItemType)
				{
					WorkItemType wit = (WorkItemType)tsi.Tag;
					WorkItem wi = wit.NewWorkItem();
					LizardWorkItem lwi = new LizardWorkItem(connection, wi);
					lwi.ShowDialog();
					if (wi.Id != 0)
					{
						if (txtWorkItems.Text.Length > 0)
						{
							txtWorkItems.Text += txtWorkItems.Text.Trim().EndsWith(",") ? string.Empty : ", ";
							txtWorkItems.Text += txtWorkItems.Text.EndsWith(" ") ? string.Empty : " ";
						}
						txtWorkItems.Text += wi.Id.ToString();
					}
				}
			}
		}

		private void btnFindWorkitems_Click(object sender, EventArgs e)
		{
			WorkItemQueries wiq = new WorkItemQueries(connection, workspace, pathList[0]);
			wiq.ShowDialog();
			int[] items = wiq.SelectedWorkItems;
			for (int i = 0; i < items.Length; i++)
			{
				if (txtWorkItems.Text.Length > 0)
				{
					txtWorkItems.Text += txtWorkItems.Text.Trim().EndsWith(",") ? string.Empty : ", ";
					txtWorkItems.Text += txtWorkItems.Text.EndsWith(" ") ? string.Empty : " ";
				}
				txtWorkItems.Text += items[i].ToString();
			}
		}

		private void elvConflicts_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
		{
			if (e.ItemIndex >= virtualItemCollection.Count)
				return;
			ExtendedListViewItem elvi = virtualItemCollection[e.ItemIndex].ConvertToExtendedListViewItem();
			e.Item = elvi;
			elvi.Ordinal = e.ItemIndex;

			if (e.Item.SubItems.Count < elvConflicts.Columns.Count)
			{
				while (elvConflicts.Columns.Count > e.Item.SubItems.Count)
				{
					e.Item.SubItems.Add("");
				}

			}
		}

		private void elvConflicts_DoHideChildren(object sender, EventArgs e)
		{
			if (e is ExtendedListViewItemEventArgs)
			{
				ExtendedListViewItem elvi = (e as ExtendedListViewItemEventArgs).ExtendedListViewItem;
				int idx = elvi.Ordinal;
				ExtendedVirtualViewItem vi = virtualItemCollection[idx];
				HideChildren(vi, idx);
			}
		}

		private void elvConflicts_DoShowChildren(object sender, EventArgs e)
		{
			if (e is ExtendedListViewItemEventArgs)
			{
				ExtendedListViewItem elvi = (e as ExtendedListViewItemEventArgs).ExtendedListViewItem;
				int idx = elvi.Ordinal;
				ExtendedVirtualViewItem vi = virtualItemCollection[idx];
				ShowChildren(vi, idx);
			}
		}

		private void elvConflicts_ItemChecked(object sender, ItemCheckedEventArgs e)
		{

		}

		private void elvConflicts_ItemCheck(object sender, ItemCheckEventArgs e)
		{

		}

		private void elvConflicts_KeyPress(object sender, KeyPressEventArgs e)
		{
			Point hit = elvConflicts.PointToClient(MousePosition);
			ListViewHitTestInfo hti = elvConflicts.HitTest(hit);
			if (hti.Item is ExtendedListViewItem)
			{
				ExtendedListViewItem elvi = hti.Item as ExtendedListViewItem;
				bool itemChecked = !elvi.VirtualItem.Checked;
				elvi.VirtualItem.IsRedrawRequired = true;
				elvi.VirtualItem.Checked = itemChecked;
				foreach (int idx in elvConflicts.SelectedIndices)
				{
					virtualItemCollection[idx].Checked = itemChecked;
					virtualItemCollection[idx].IsRedrawRequired = true;
				}
				checked { };
				elvConflicts.Invalidate();
			}
		}


	}



	public class Sorter : IComparer
	{
		private int sortColumnIndex;
		private int descMultiplier;

		public Sorter(int sortColumnIndex, bool desc)
		{
			this.sortColumnIndex = sortColumnIndex;
			descMultiplier = (desc ? -1 : 1);
		}
		#region IComparer<ListViewItem> Members

		public int Compare(object x, object y)
		{
			ListViewItem lviX = (ListViewItem)x;
			ListViewItem lviY = (ListViewItem)y;
			if (lviX.SubItems.Count <= sortColumnIndex)
				return -1;
			if (lviY.SubItems.Count <= sortColumnIndex)
				return 1;
			string xText = lviX.SubItems[sortColumnIndex].Text;
			string yText = lviY.SubItems[sortColumnIndex].Text;

			double xNumber = 0, yNumber = 0;
			DateTime xDate, yDate;
			if (double.TryParse(xText, out xNumber) && double.TryParse(yText, out yNumber))
				return xNumber.CompareTo(yNumber) * descMultiplier;
			else if (DateTime.TryParse(xText, out xDate) && DateTime.TryParse(yText, out yDate))
				return xDate.CompareTo(yDate) * descMultiplier;
			return xText.CompareTo(yText) * descMultiplier;
		}

		#endregion
	}

	public class VirtualSorter : IComparer<ExtendedVirtualViewItem>
	{
		private bool byLocation;
		private int sortColumnIndex;
		private int descMultiplier;

		public VirtualSorter(bool byLocation, int sortColumnIndex, bool desc)
		{
			this.byLocation = byLocation;
			this.sortColumnIndex = sortColumnIndex;
			descMultiplier = (desc ? -1 : 1);
		}
		#region IComparer<string[]> Members

		public int Compare(ExtendedVirtualViewItem x, ExtendedVirtualViewItem y)
		{
			x.IsRedrawRequired = true;
			y.IsRedrawRequired = true;
			int groupCompare = x.GroupIdx.CompareTo(y.GroupIdx);
			if (groupCompare != 0)
				return groupCompare;

			int groupHeaderCompare = x.GroupHeaderIdx.CompareTo(y.GroupHeaderIdx);
			if (groupHeaderCompare != 0)
				return groupHeaderCompare;


			if (byLocation)
			{
				if (x.Location != null && y.Location != null)
				{
					int locationCompare = x.Location.CompareTo(y.Location);
					if (locationCompare != 0)
						return locationCompare;
					else if (x.IsFolder && !y.IsFolder)
						return -1;
					else if (!x.IsFolder && y.IsFolder)
						return 1;
				}
			}

			if (x.Items.Length <= sortColumnIndex && y.Items.Length <= sortColumnIndex)
				return 0;

			if (x.Items.Length <= sortColumnIndex)
				return -1;
			if (y.Items.Length <= sortColumnIndex)
				return 1;
			string xText = x.Items[sortColumnIndex];
			string yText = y.Items[sortColumnIndex];

			double xNumber = 0, yNumber = 0;
			DateTime xDate, yDate;
			if (double.TryParse(xText, out xNumber) && double.TryParse(yText, out yNumber))
				return xNumber.CompareTo(yNumber) * descMultiplier;
			else if (DateTime.TryParse(xText, out xDate) && DateTime.TryParse(yText, out yDate))
				return xDate.CompareTo(yDate) * descMultiplier;
			return xText.CompareTo(yText) * descMultiplier;
		}

		#endregion
	}
}




